package com.bt7274.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bt7274.enums.*;
import com.bt7274.exception.BusinessException;
import com.bt7274.mapper.*;
import com.bt7274.pojo.*;
import com.bt7274.pojo.bo.*;
import com.bt7274.pojo.vo.*;
import com.bt7274.service.AssessmentService;
import com.bt7274.utils.PageResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @BelongsProject: bt7274-back
 * @BelongsPackage: com.bt7274.service.impl
 * @Author: Galland
 * @CreateTime: 2025-06-14
 * @Description: 用户考核服务实现
 * @Version: 1.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AssessmentServiceImpl implements AssessmentService {

    private final UserRuleMapper userRuleMapper;
    private final AssessmentMapper assessmentMapper;
    private final UserMapper userMapper;
    private final UserExpMapper userExpMapper;
    private final PtRecordMapper ptRecordMapper;
    private final PostMapper postMapper;
    private final BtTransactionMapper btTransactionMapper;
    private final NotificationMapper notificationMapper;

    @Override
    @Transactional
    public Integer createAssessmentRule(CreateUserRuleBO ruleBO) {
        // 验证指标类型
        AssessmentMetricType metricType = AssessmentMetricType.getByMetricKey(ruleBO.getMetric());
        if (metricType == null) {
            throw new BusinessException("无效的考核指标：" + ruleBO.getMetric());
        }

        // 验证惩罚类型
        try {
            AssessmentPenaltyType.valueOf(ruleBO.getPenalty());
        } catch (IllegalArgumentException e) {
            throw new BusinessException("无效的惩罚类型：" + ruleBO.getPenalty());
        }

        UserRule rule = new UserRule();
        rule.setName(ruleBO.getName());
        rule.setMetric(ruleBO.getMetric());
        rule.setThreshold(ruleBO.getThreshold());
        rule.setCycleDays(ruleBO.getCycleDays());
        rule.setPenalty(ruleBO.getPenalty());
        rule.setPriority(ruleBO.getPriority());
        rule.setDescription(ruleBO.getDescription());
        rule.setIsActive(1);
        rule.setCreatedTime(LocalDateTime.now());
        rule.setUpdatedTime(LocalDateTime.now());

        // 设置豁免权限组
        if (ruleBO.getExemptGroups() != null && !ruleBO.getExemptGroups().isEmpty()) {
            rule.setExemptGroups(ruleBO.getExemptGroups().stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(",")));
        }

        userRuleMapper.insert(rule);
        log.info("创建考核规则：{}", rule.getName());

        return rule.getId();
    }

    @Override
    @Transactional
    public void updateAssessmentRule(UpdateUserRuleBO ruleBO) {
        UserRule rule = userRuleMapper.selectById(ruleBO.getId());
        if (rule == null) {
            throw new BusinessException("考核规则不存在");
        }

        // 更新非空字段
        if (ruleBO.getName() != null) {
            rule.setName(ruleBO.getName());
        }
        if (ruleBO.getMetric() != null) {
            AssessmentMetricType metricType = AssessmentMetricType.getByMetricKey(ruleBO.getMetric());
            if (metricType == null) {
                throw new BusinessException("无效的考核指标：" + ruleBO.getMetric());
            }
            rule.setMetric(ruleBO.getMetric());
        }
        if (ruleBO.getThreshold() != null) {
            rule.setThreshold(ruleBO.getThreshold());
        }
        if (ruleBO.getCycleDays() != null) {
            rule.setCycleDays(ruleBO.getCycleDays());
        }
        if (ruleBO.getPenalty() != null) {
            try {
                AssessmentPenaltyType.valueOf(ruleBO.getPenalty());
            } catch (IllegalArgumentException e) {
                throw new BusinessException("无效的惩罚类型：" + ruleBO.getPenalty());
            }
            rule.setPenalty(ruleBO.getPenalty());
        }
        if (ruleBO.getIsActive() != null) {
            rule.setIsActive(ruleBO.getIsActive());
        }
        if (ruleBO.getPriority() != null) {
            rule.setPriority(ruleBO.getPriority());
        }
        if (ruleBO.getDescription() != null) {
            rule.setDescription(ruleBO.getDescription());
        }
        if (ruleBO.getExemptGroups() != null) {
            rule.setExemptGroups(ruleBO.getExemptGroups().stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(",")));
        }

        rule.setUpdatedTime(LocalDateTime.now());
        userRuleMapper.updateById(rule);

        log.info("更新考核规则：{}", rule.getName());
    }

    @Override
    @Transactional
    public void deleteAssessmentRule(Integer ruleId) {
        UserRule rule = userRuleMapper.selectById(ruleId);
        if (rule == null) {
            throw new BusinessException("考核规则不存在");
        }

        // 检查是否有考核记录
        QueryWrapper<Assessment> wrapper = new QueryWrapper<>();
        wrapper.eq("rule_id", ruleId);
        Long count = assessmentMapper.selectCount(wrapper);

        if (count > 0) {
            throw new BusinessException("该规则已有考核记录，无法删除");
        }

        userRuleMapper.deleteById(ruleId);
        log.info("删除考核规则：{}", rule.getName());
    }

    @Override
    public void toggleRuleStatus(Integer ruleId, Integer isActive) {
        UserRule rule = userRuleMapper.selectById(ruleId);
        if (rule == null) {
            throw new BusinessException("考核规则不存在");
        }

        rule.setIsActive(isActive);
        rule.setUpdatedTime(LocalDateTime.now());
        userRuleMapper.updateById(rule);

        log.info("{}考核规则：{}", isActive == 1 ? "启用" : "禁用", rule.getName());
    }

    @Override
    public PageResponse<UserRuleVO> getAssessmentRules(Integer current, Integer size, Integer isActive) {
        Page<UserRule> page = new Page<>(current, size);
        QueryWrapper<UserRule> wrapper = new QueryWrapper<>();

        if (isActive != null) {
            wrapper.eq("is_active", isActive);
        }

        wrapper.orderByAsc("priority").orderByDesc("created_time");
        Page<UserRule> rulePage = userRuleMapper.selectPage(page, wrapper);

        List<UserRuleVO> ruleVOList = rulePage.getRecords().stream()
                .map(this::convertToRuleVO)
                .collect(Collectors.toList());

        return new PageResponse<>(ruleVOList, rulePage.getTotal(),
                rulePage.getCurrent(), rulePage.getSize());
    }

    @Override
    public UserRuleVO getRuleDetail(Integer ruleId) {
        UserRule rule = userRuleMapper.selectById(ruleId);
        if (rule == null) {
            throw new BusinessException("考核规则不存在");
        }

        return convertToRuleVO(rule);
    }

    @Override
    @Transactional
    public BatchAssessmentResultVO executeAutoAssessment() {
        log.info("开始执行自动考核任务...");
        LocalDateTime startTime = LocalDateTime.now();
        BatchAssessmentResultVO result = new BatchAssessmentResultVO();
        result.setStartTime(startTime);

        // 获取所有启用的规则
        QueryWrapper<UserRule> ruleWrapper = new QueryWrapper<>();
        ruleWrapper.eq("is_active", 1).orderByAsc("priority");
        List<UserRule> activeRules = userRuleMapper.selectList(ruleWrapper);

        if (activeRules.isEmpty()) {
            log.info("没有启用的考核规则");
            result.setEndTime(LocalDateTime.now());
            return result;
        }

        // 统计数据
        Set<String> allUsers = new HashSet<>();
        int totalAssessed = 0;
        int totalPassed = 0;
        int totalFailed = 0;
        int totalExempted = 0;
        int penaltiesApplied = 0;
        List<String> errors = new ArrayList<>();

        // 按规则执行考核
        for (UserRule rule : activeRules) {
            try {
                List<String> usersToAssess = getUsersForAssessment(rule.getId());
                allUsers.addAll(usersToAssess);

                for (String userId : usersToAssess) {
                    try {
                        // 检查是否豁免
                        if (isUserExempted(userId, rule.getId())) {
                            totalExempted++;
                            continue;
                        }

                        // 执行考核
                        AssessmentResultVO assessResult = assessSingleUserRule(userId, rule);
                        totalAssessed++;

                        if (assessResult.getIsPassed()) {
                            totalPassed++;
                        } else {
                            totalFailed++;
                            // 执行惩罚
                            if (applyPenalty(userId, rule.getPenalty(),
                                    "未通过考核：" + rule.getName())) {
                                penaltiesApplied++;
                            }
                        }
                    } catch (Exception e) {
                        errors.add(String.format("用户 %s 规则 %s 考核失败：%s",
                                userId, rule.getName(), e.getMessage()));
                        log.error("考核用户 {} 规则 {} 失败", userId, rule.getName(), e);
                    }
                }
            } catch (Exception e) {
                errors.add(String.format("规则 %s 执行失败：%s", rule.getName(), e.getMessage()));
                log.error("执行规则 {} 失败", rule.getName(), e);
            }
        }

        // 设置结果
        result.setTotalUsers(allUsers.size());
        result.setAssessedUsers(totalAssessed);
        result.setPassedUsers(totalPassed);
        result.setFailedUsers(totalFailed);
        result.setExemptedUsers(totalExempted);
        result.setPenaltiesApplied(penaltiesApplied);
        result.setErrors(errors);
        result.setEndTime(LocalDateTime.now());
        result.setDuration(ChronoUnit.MILLIS.between(startTime, result.getEndTime()));

        log.info("自动考核完成，总用户：{}，考核：{}，通过：{}，未通过：{}，豁免：{}，执行惩罚：{}",
                result.getTotalUsers(), result.getAssessedUsers(), result.getPassedUsers(),
                result.getFailedUsers(), result.getExemptedUsers(), result.getPenaltiesApplied());

        return result;
    }

    @Override
    @Transactional
    public BatchAssessmentResultVO executeManualAssessment(ManualAssessmentBO assessmentBO) {
        BatchAssessmentResultVO result = new BatchAssessmentResultVO();
        result.setStartTime(LocalDateTime.now());

        List<String> usersToAssess = new ArrayList<>();
        List<UserRule> rulesToApply = new ArrayList<>();

        // 确定要考核的用户
        if (assessmentBO.getUserId() != null) {
            usersToAssess.add(assessmentBO.getUserId());
        } else {
            // 获取所有活跃用户
            QueryWrapper<User> userWrapper = new QueryWrapper<>();
            userWrapper.eq("status", 0); // 正常状态
            List<User> users = userMapper.selectList(userWrapper);
            usersToAssess = users.stream().map(User::getId).collect(Collectors.toList());
        }

        // 确定要应用的规则
        if (assessmentBO.getRuleId() != null) {
            UserRule rule = userRuleMapper.selectById(assessmentBO.getRuleId());
            if (rule != null && rule.getIsActive() == 1) {
                rulesToApply.add(rule);
            }
        } else {
            QueryWrapper<UserRule> ruleWrapper = new QueryWrapper<>();
            ruleWrapper.eq("is_active", 1).orderByAsc("priority");
            rulesToApply = userRuleMapper.selectList(ruleWrapper);
        }

        // 执行考核
        int totalAssessed = 0;
        int totalPassed = 0;
        int totalFailed = 0;
        int totalExempted = 0;
        List<String> errors = new ArrayList<>();

        for (String userId : usersToAssess) {
            for (UserRule rule : rulesToApply) {
                try {
                    if (isUserExempted(userId, rule.getId())) {
                        totalExempted++;
                        continue;
                    }

                    AssessmentResultVO assessResult = assessSingleUserRule(userId, rule);
                    totalAssessed++;

                    if (assessResult.getIsPassed()) {
                        totalPassed++;
                    } else {
                        totalFailed++;
                    }
                } catch (Exception e) {
                    errors.add(String.format("用户 %s 规则 %s 考核失败：%s",
                            userId, rule.getName(), e.getMessage()));
                }
            }
        }

        result.setTotalUsers(usersToAssess.size());
        result.setAssessedUsers(totalAssessed);
        result.setPassedUsers(totalPassed);
        result.setFailedUsers(totalFailed);
        result.setExemptedUsers(totalExempted);
        result.setErrors(errors);
        result.setEndTime(LocalDateTime.now());
        result.setDuration(ChronoUnit.MILLIS.between(result.getStartTime(), result.getEndTime()));

        return result;
    }

    @Override
    @Transactional
    public List<AssessmentResultVO> assessUser(String userId, Integer ruleId) {
        List<AssessmentResultVO> results = new ArrayList<>();

        if (ruleId != null) {
            // 考核指定规则
            UserRule rule = userRuleMapper.selectById(ruleId);
            if (rule != null && rule.getIsActive() == 1) {
                results.add(assessSingleUserRule(userId, rule));
            }
        } else {
            // 考核所有规则
            QueryWrapper<UserRule> wrapper = new QueryWrapper<>();
            wrapper.eq("is_active", 1).orderByAsc("priority");
            List<UserRule> rules = userRuleMapper.selectList(wrapper);

            for (UserRule rule : rules) {
                if (!isUserExempted(userId, rule.getId())) {
                    results.add(assessSingleUserRule(userId, rule));
                }
            }
        }

        return results;
    }

    @Override
    public UserAssessmentStatusVO getUserAssessmentStatus(String userId) {
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        UserAssessmentStatusVO status = new UserAssessmentStatusVO();
        status.setUserId(userId);
        status.setUsername(user.getUsername());
        status.setPermissionGroup(user.getPermissionGroup());

        // 获取当前周期的考核结果
        List<AssessmentResultVO> currentAssessments = new ArrayList<>();
        QueryWrapper<UserRule> ruleWrapper = new QueryWrapper<>();
        ruleWrapper.eq("is_active", 1);
        List<UserRule> activeRules = userRuleMapper.selectList(ruleWrapper);

        for (UserRule rule : activeRules) {
            // 获取最近一次考核记录
            QueryWrapper<Assessment> assessWrapper = new QueryWrapper<>();
            assessWrapper.eq("user_id", userId)
                    .eq("rule_id", rule.getId())
                    .orderByDesc("assessed_time")
                    .last("LIMIT 1");
            Assessment lastAssessment = assessmentMapper.selectOne(assessWrapper);

            if (lastAssessment != null) {
                AssessmentResultVO resultVO = convertToResultVO(lastAssessment, rule);
                currentAssessments.add(resultVO);
            }
        }

        status.setCurrentAssessments(currentAssessments);

        // 获取最近的考核记录
        QueryWrapper<Assessment> recentWrapper = new QueryWrapper<>();
        recentWrapper.eq("user_id", userId)
                .orderByDesc("assessed_time")
                .last("LIMIT 10");
        List<Assessment> recentAssessments = assessmentMapper.selectList(recentWrapper);

        List<AssessmentResultVO> recentResults = new ArrayList<>();
        for (Assessment assessment : recentAssessments) {
            UserRule rule = userRuleMapper.selectById(assessment.getRuleId());
            if (rule != null) {
                recentResults.add(convertToResultVO(assessment, rule));
            }
        }
        status.setRecentAssessments(recentResults);

        // 统计通过/未通过次数
        QueryWrapper<Assessment> statsWrapper = new QueryWrapper<>();
        statsWrapper.eq("user_id", userId);
        List<Assessment> allAssessments = assessmentMapper.selectList(statsWrapper);

        int totalPassed = (int) allAssessments.stream().filter(a -> a.getIsPassed() == 1).count();
        int totalFailed = allAssessments.size() - totalPassed;

        status.setTotalPassed(totalPassed);
        status.setTotalFailed(totalFailed);

        // 检查是否有生效的警告
        status.setHasActiveWarning(getUserActivePenalties(userId).contains("WARNING"));

        // 计算下次考核时间
        LocalDateTime nextAssessmentTime = calculateNextAssessmentTime(userId);
        status.setNextAssessmentTime(nextAssessmentTime);

        return status;
    }

    @Override
    public PageResponse<AssessmentResultVO> getUserAssessmentHistory(
            String userId, Integer current, Integer size,
            LocalDateTime startTime, LocalDateTime endTime) {
        Page<Assessment> page = new Page<>(current, size);
        QueryWrapper<Assessment> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);

        if (startTime != null) {
            wrapper.ge("assessed_time", startTime);
        }
        if (endTime != null) {
            wrapper.le("assessed_time", endTime);
        }

        wrapper.orderByDesc("assessed_time");
        Page<Assessment> assessmentPage = assessmentMapper.selectPage(page, wrapper);

        List<AssessmentResultVO> results = new ArrayList<>();
        for (Assessment assessment : assessmentPage.getRecords()) {
            UserRule rule = userRuleMapper.selectById(assessment.getRuleId());
            if (rule != null) {
                results.add(convertToResultVO(assessment, rule));
            }
        }

        return new PageResponse<>(results, assessmentPage.getTotal(),
                assessmentPage.getCurrent(), assessmentPage.getSize());
    }

    @Override
    public List<AssessmentStatisticsVO> getAssessmentStatistics(
            Integer ruleId, LocalDateTime startTime, LocalDateTime endTime) {
        List<AssessmentStatisticsVO> statistics = new ArrayList<>();

        List<UserRule> rules = new ArrayList<>();
        if (ruleId != null) {
            UserRule rule = userRuleMapper.selectById(ruleId);
            if (rule != null) {
                rules.add(rule);
            }
        } else {
            rules = userRuleMapper.selectList(null);
        }

        for (UserRule rule : rules) {
            QueryWrapper<Assessment> wrapper = new QueryWrapper<>();
            wrapper.eq("rule_id", rule.getId());

            if (startTime != null) {
                wrapper.ge("assessed_time", startTime);
            }
            if (endTime != null) {
                wrapper.le("assessed_time", endTime);
            }

            List<Assessment> assessments = assessmentMapper.selectList(wrapper);

            if (!assessments.isEmpty()) {
                AssessmentStatisticsVO stat = new AssessmentStatisticsVO();
                stat.setRuleId(rule.getId().toString());
                stat.setRuleName(rule.getName());
                stat.setTotalAssessed(assessments.size());
                stat.setPassedCount((int) assessments.stream()
                        .filter(a -> a.getIsPassed() == 1).count());
                stat.setFailedCount(stat.getTotalAssessed() - stat.getPassedCount());
                stat.setPassRate((float) stat.getPassedCount() / stat.getTotalAssessed() * 100);

                // 计算平均值
                double avgValue = assessments.stream()
                        .mapToDouble(Assessment::getCurrentValue)
                        .average()
                        .orElse(0.0);
                stat.setAverageValue((float) avgValue);

                stat.setStatisticsTime(LocalDateTime.now());
                statistics.add(stat);
            }
        }

        return statistics;
    }

    @Override
    @Transactional
    public boolean applyPenalty(String userId, String penalty, String reason) {
        try {
            AssessmentPenaltyType penaltyType = AssessmentPenaltyType.valueOf(penalty);
            User user = userMapper.selectById(userId);
            if (user == null) {
                return false;
            }

            switch (penaltyType) {
                case WARNING:
                    // 发送警告通知
                    sendNotification(userId, "考核警告", reason, "warning");
                    break;

                case LIMIT_DOWNLOAD:
                    // 限制下载权限
                    updateUserPermission(userId, "can_download", 0);
                    sendNotification(userId, "下载权限限制", reason, "penalty");
                    break;

                case LIMIT_INVITE:
                    // 限制邀请权限
                    updateUserPermission(userId, "can_invite", 0);
                    sendNotification(userId, "邀请权限限制", reason, "penalty");
                    break;

                case REDUCE_BT_COINS:
                    // 扣除BT币
                    deductBtCoins(userId, 100, reason); // 默认扣除100
                    break;

                case DEMOTE_LEVEL:
                    // 降级
                    if (user.getPermissionGroup() > 0) {
                        user.setPermissionGroup(user.getPermissionGroup() - 1);
                        userMapper.updateById(user);
                        sendNotification(userId, "权限等级降级", reason, "penalty");
                    }
                    break;

                case BAN_ACCOUNT:
                    // 封禁账号
                    user.setStatus(1); // 封禁状态
                    userMapper.updateById(user);
                    sendNotification(userId, "账号封禁", reason, "severe_penalty");
                    break;
            }

            log.info("对用户 {} 执行惩罚 {}，原因：{}", userId, penalty, reason);
            return true;
        } catch (Exception e) {
            log.error("执行惩罚失败", e);
            return false;
        }
    }

    @Override
    @Transactional
    public boolean revokePenalty(String userId, String penalty, String reason) {
        try {
            AssessmentPenaltyType penaltyType = AssessmentPenaltyType.valueOf(penalty);
            User user = userMapper.selectById(userId);
            if (user == null) {
                return false;
            }

            switch (penaltyType) {
                case LIMIT_DOWNLOAD:
                    updateUserPermission(userId, "can_download", 1);
                    break;
                case LIMIT_INVITE:
                    updateUserPermission(userId, "can_invite", 1);
                    break;
                case BAN_ACCOUNT:
                    user.setStatus(0); // 恢复正常状态
                    userMapper.updateById(user);
                    break;
            }

            sendNotification(userId, "惩罚撤销", reason, "info");
            log.info("撤销用户 {} 的惩罚 {}，原因：{}", userId, penalty, reason);
            return true;
        } catch (Exception e) {
            log.error("撤销惩罚失败", e);
            return false;
        }
    }

    @Override
    public List<String> getUserActivePenalties(String userId) {
        List<String> penalties = new ArrayList<>();

        // 检查最近的考核记录
        QueryWrapper<Assessment> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId)
                .eq("is_passed", 0)
                .ge("assessed_time", LocalDateTime.now().minusDays(30))
                .isNotNull("penalty_applied");

        List<Assessment> failedAssessments = assessmentMapper.selectList(wrapper);
        penalties = failedAssessments.stream()
                .map(Assessment::getPenaltyApplied)
                .filter(p -> p != null && !p.isEmpty())
                .distinct()
                .collect(Collectors.toList());

        return penalties;
    }

    @Override
    public Float calculateUserMetric(String userId, String metric) {
        AssessmentMetricType metricType = AssessmentMetricType.getByMetricKey(metric);
        if (metricType == null) {
            return 0.0f;
        }

        UserExp userExp = userExpMapper.selectById(userId);
        User user = userMapper.selectById(userId);

        switch (metricType) {
            case SHARE_RATIO:
                if (userExp != null) {
                    return userExp.getRatio().floatValue();
                }
                break;

            case SEEDING_TIME:
                if (userExp != null) {
                    // 转换为小时
                    return userExp.getSeedingTime() / 3600.0f;
                }
                break;

            case UPLOAD_AMOUNT:
                if (userExp != null) {
                    // 转换为GB
                    return userExp.getUploaded() / (1024.0f * 1024.0f * 1024.0f);
                }
                break;

            case DOWNLOAD_AMOUNT:
                if (userExp != null) {
                    // 转换为GB
                    return userExp.getDownloaded() / (1024.0f * 1024.0f * 1024.0f);
                }
                break;

            case ACTIVE_SEEDS:
                QueryWrapper<PtRecord> seedWrapper = new QueryWrapper<>();
                seedWrapper.eq("user_id", userId).eq("seeding", 1);
                return (float) ptRecordMapper.selectCount(seedWrapper);

            case BT_COINS:
                if (userExp != null) {
                    return (float) userExp.getBt();
                }
                break;

            case ONLINE_TIME:
                // TODO: 实现在线时长统计
                return 0.0f;

            case FORUM_POSTS:
                QueryWrapper<Post> postWrapper = new QueryWrapper<>();
                postWrapper.eq("user_id", userId);
                return (float) postMapper.selectCount(postWrapper);

            case REGISTRATION_DAYS:
                if (user != null) {
                    long days = ChronoUnit.DAYS.between(user.getCreatedTime(), LocalDateTime.now());
                    return (float) days;
                }
                break;
        }

        return 0.0f;
    }

    @Override
    public boolean isUserExempted(String userId, Integer ruleId) {
        User user = userMapper.selectById(userId);
        UserRule rule = userRuleMapper.selectById(ruleId);

        if (user == null || rule == null) {
            return false;
        }

        // 检查用户权限组是否在豁免列表中
        if (rule.getExemptGroups() != null && !rule.getExemptGroups().isEmpty()) {
            String[] exemptGroups = rule.getExemptGroups().split(",");
            for (String group : exemptGroups) {
                try {
                    if (Integer.parseInt(group.trim()) == user.getPermissionGroup()) {
                        return true;
                    }
                } catch (NumberFormatException e) {
                    // 忽略无效的权限组
                }
            }
        }

        // 检查全局豁免级别
        if (user.getPermissionGroup() >= AssessmentExemptionLevel.FULL.getMinPermissionGroup()) {
            return true; // 完全豁免
        }

        // 部分豁免逻辑（可以根据具体规则进一步细化）
        if (user.getPermissionGroup() >= AssessmentExemptionLevel.PARTIAL.getMinPermissionGroup()) {
            // 某些严重的惩罚类型不豁免
            AssessmentPenaltyType penaltyType = AssessmentPenaltyType.valueOf(rule.getPenalty());
            if (!penaltyType.isSevere()) {
                return true;
            }
        }

        return false;
    }

    @Override
    public List<String> getUsersForAssessment(Integer ruleId) {
        UserRule rule = userRuleMapper.selectById(ruleId);
        if (rule == null) {
            return new ArrayList<>();
        }

        // 获取需要考核的用户
        QueryWrapper<User> userWrapper = new QueryWrapper<>();
        userWrapper.eq("status", 0); // 正常状态的用户

        // 排除豁免的权限组
        if (rule.getExemptGroups() != null && !rule.getExemptGroups().isEmpty()) {
            String[] exemptGroups = rule.getExemptGroups().split(",");
            userWrapper.notIn("permission_group", Arrays.asList(exemptGroups));
        }

        // 获取最近一次考核时间
        LocalDateTime lastAssessmentTime = LocalDateTime.now().minusDays(rule.getCycleDays());

        List<User> users = userMapper.selectList(userWrapper);
        List<String> usersToAssess = new ArrayList<>();

        for (User user : users) {
            // 检查是否需要考核
            QueryWrapper<Assessment> assessWrapper = new QueryWrapper<>();
            assessWrapper.eq("user_id", user.getId())
                    .eq("rule_id", ruleId)
                    .ge("assessed_time", lastAssessmentTime);

            if (assessmentMapper.selectCount(assessWrapper) == 0) {
                usersToAssess.add(user.getId());
            }
        }

        return usersToAssess;
    }

    @Override
    public void sendAssessmentNotification(String userId, AssessmentResultVO result) {
        String title = result.getIsPassed() ? "考核通过通知" : "考核未通过通知";
        String content = String.format("您在 %s 考核中%s，当前值：%.2f，要求值：%.2f",
                result.getRuleName(),
                result.getIsPassed() ? "通过" : "未通过",
                result.getCurrentValue(),
                result.getThreshold());

        sendNotification(userId, title, content, result.getIsPassed() ? "info" : "warning");
    }

    // ========== 私有辅助方法 ==========

    private UserRuleVO convertToRuleVO(UserRule rule) {
        UserRuleVO vo = new UserRuleVO();
        vo.setId(rule.getId());
        vo.setName(rule.getName());
        vo.setMetric(rule.getMetric());
        vo.setThreshold(rule.getThreshold());
        vo.setCycleDays(rule.getCycleDays());
        vo.setPenalty(rule.getPenalty());
        vo.setIsActive(rule.getIsActive());
        vo.setPriority(rule.getPriority());
        vo.setDescription(rule.getDescription());

        // 设置描述信息
        AssessmentMetricType metricType = AssessmentMetricType.getByMetricKey(rule.getMetric());
        if (metricType != null) {
            vo.setMetricDescription(metricType.getDescription());
        }

        for (AssessmentCycleType cycleType : AssessmentCycleType.values()) {
            if (cycleType.getDays() == rule.getCycleDays()) {
                vo.setCycleDescription(cycleType.getDescription());
                break;
            }
        }

        try {
            AssessmentPenaltyType penaltyType = AssessmentPenaltyType.valueOf(rule.getPenalty());
            vo.setPenaltyDescription(penaltyType.getDescription());
        } catch (Exception e) {
            // 忽略
        }

        // 解析豁免权限组
        if (rule.getExemptGroups() != null && !rule.getExemptGroups().isEmpty()) {
            vo.setExemptGroups(Arrays.stream(rule.getExemptGroups().split(","))
                    .map(String::trim)
                    .map(Integer::parseInt)
                    .collect(Collectors.toList()));
        }

        // 统计受影响用户数和通过率
        List<String> affectedUsers = getUsersForAssessment(rule.getId());
        vo.setAffectedUsers(affectedUsers.size());

        // 计算通过率
        QueryWrapper<Assessment> assessWrapper = new QueryWrapper<>();
        assessWrapper.eq("rule_id", rule.getId())
                .ge("assessed_time", LocalDateTime.now().minusDays(30)); // 最近30天
        List<Assessment> recentAssessments = assessmentMapper.selectList(assessWrapper);

        if (!recentAssessments.isEmpty()) {
            long passedCount = recentAssessments.stream()
                    .filter(a -> a.getIsPassed() == 1).count();
            vo.setPassRate((float) passedCount / recentAssessments.size() * 100);
        }

        return vo;
    }

    private AssessmentResultVO convertToResultVO(Assessment assessment, UserRule rule) {
        AssessmentResultVO vo = new AssessmentResultVO();
        vo.setAssessmentId(assessment.getId());
        vo.setRuleId(assessment.getRuleId());
        vo.setRuleName(rule.getName());
        vo.setMetric(rule.getMetric());
        vo.setThreshold(rule.getThreshold());
        vo.setCurrentValue(assessment.getCurrentValue());
        vo.setIsPassed(assessment.getIsPassed() == 1);
        vo.setPenaltyApplied(assessment.getPenaltyApplied());
        vo.setAssessedTime(assessment.getAssessedTime());

        // 设置状态
        if (vo.getIsPassed()) {
            vo.setStatus("PASS");
        } else if (assessment.getPenaltyApplied() != null &&
                assessment.getPenaltyApplied().equals("WARNING")) {
            vo.setStatus("WARNING");
        } else {
            vo.setStatus("FAIL");
        }

        // 计算距离下次考核天数
        long daysSinceAssessment = ChronoUnit.DAYS.between(
                assessment.getAssessedTime(), LocalDateTime.now());
        vo.setDaysUntilNext((int) (rule.getCycleDays() - daysSinceAssessment));

        return vo;
    }

    private AssessmentResultVO assessSingleUserRule(String userId, UserRule rule) {
        // 计算用户当前指标值
        Float currentValue = calculateUserMetric(userId, rule.getMetric());

        // 判断是否通过
        boolean isPassed = false;
        AssessmentMetricType metricType = AssessmentMetricType.getByMetricKey(rule.getMetric());

        // 根据不同指标类型判断
        switch (metricType) {
            case SHARE_RATIO:
            case SEEDING_TIME:
            case UPLOAD_AMOUNT:
            case ACTIVE_SEEDS:
            case BT_COINS:
            case ONLINE_TIME:
            case FORUM_POSTS:
            case REGISTRATION_DAYS:
                // 这些指标要求大于等于阈值
                isPassed = currentValue >= rule.getThreshold();
                break;
            case DOWNLOAD_AMOUNT:
                // 这些指标要求小于等于阈值
                isPassed = currentValue <= rule.getThreshold();
                break;
        }

        // 创建考核记录
        Assessment assessment = new Assessment();
        assessment.setId(UUID.randomUUID().toString().replace("-", ""));
        assessment.setUserId(userId);
        assessment.setRuleId(rule.getId().toString());
        assessment.setCurrentValue(currentValue);
        assessment.setIsPassed(isPassed ? 1 : 0);
        assessment.setAssessedTime(LocalDateTime.now());

        if (!isPassed) {
            assessment.setPenaltyApplied(rule.getPenalty());
        }

        assessmentMapper.insert(assessment);

        // 发送通知
        AssessmentResultVO result = convertToResultVO(assessment, rule);
        sendAssessmentNotification(userId, result);

        return result;
    }

    private LocalDateTime calculateNextAssessmentTime(String userId) {
        // 获取所有活跃规则的下次考核时间
        QueryWrapper<UserRule> ruleWrapper = new QueryWrapper<>();
        ruleWrapper.eq("is_active", 1);
        List<UserRule> activeRules = userRuleMapper.selectList(ruleWrapper);

        LocalDateTime nextTime = null;

        for (UserRule rule : activeRules) {
            // 获取该规则的最后考核时间
            QueryWrapper<Assessment> assessWrapper = new QueryWrapper<>();
            assessWrapper.eq("user_id", userId)
                    .eq("rule_id", rule.getId())
                    .orderByDesc("assessed_time")
                    .last("LIMIT 1");
            Assessment lastAssessment = assessmentMapper.selectOne(assessWrapper);

            LocalDateTime ruleNextTime;
            if (lastAssessment != null) {
                ruleNextTime = lastAssessment.getAssessedTime().plusDays(rule.getCycleDays());
            } else {
                // 如果没有考核记录，下次考核时间为现在
                ruleNextTime = LocalDateTime.now();
            }

            if (nextTime == null || ruleNextTime.isBefore(nextTime)) {
                nextTime = ruleNextTime;
            }
        }

        return nextTime;
    }

    private void updateUserPermission(String userId, String permission, Integer value) {
        // TODO: 根据permission更新用户对应的权限
        // 这里需要根据实际的权限系统实现
    }

    private void deductBtCoins(String userId, int amount, String reason) {
        UserExp userExp = userExpMapper.selectById(userId);
        if (userExp != null && userExp.getBt() >= amount) {
            userExp.setBt(userExp.getBt() - amount);
            userExpMapper.updateById(userExp);

            // 记录BT币变动
            BtTransaction transaction = new BtTransaction();
            transaction.setId(UUID.randomUUID().toString().replace("-", ""));
            transaction.setUserId(userId);
            transaction.setPoints(-amount);
            transaction.setType("ASSESSMENT_PENALTY");
            transaction.setRuleId("ASSESSMENT");
            transaction.setDescription(reason);
            transaction.setCreatedTime(LocalDateTime.now());
            btTransactionMapper.insert(transaction);
        }
    }

    private void sendNotification(String userId, String title, String content, String type) {
        try {
            Notification notification = new Notification();
            notification.setType(type);
            notification.setReceiverId(userId);
            notification.setContent(title + ": " + content);
            notification.setIsRead(false);
            notification.setCreatedTime(LocalDateTime.now());

            notificationMapper.insert(notification);
            log.info("发送通知给用户 {}：{} - {}", userId, title, content);
        } catch (Exception e) {
            log.error("发送通知失败", e);
        }
    }
}
